﻿using System;
using System.Threading;
using System.Globalization;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace AntsCode.WordsExtensions
{
    internal class MergeFieldFormatter
    {
        public static string FormatValue(MergeField mergeField, string value)
        {
            foreach (MergeFieldSwitch fieldSwitch in mergeField.Switches)
            {
                value = MergeFieldFormatter.FormatValue(fieldSwitch.Name, fieldSwitch.Value, value);
            }

            return value;
        }

        public static string FormatValue(string switchType, string switchValue, string value)
        {
            switch (switchType)
            {
                case "*":
                    value = MergeFieldFormatter.ProcessFormatSwitch(switchValue, value);
                    break;

                case "#":
                    value = MergeFieldFormatter.ProcessNumericSwitch(switchValue, value);
                    break;

                case "@":
                    value = MergeFieldFormatter.ProcessDateTimeSwitch(switchValue, value);
                    break;
            }

            return value;
        }

        private static string ProcessFormatSwitch(string switchValue, string value)
        {
            CultureInfo cultureInfo = Thread.CurrentThread.CurrentCulture;
            TextInfo textInfo = cultureInfo.TextInfo;

            switch (switchValue.ToLower())
            {
                case "caps":
                    value = textInfo.ToTitleCase(value);
                    break;

                case "firstcap":
                    value = MergeFieldFormatter.UppercaseFirst(value);
                    break;

                case "upper":
                    value = textInfo.ToUpper(value);
                    break;

                case "lower":
                    value = textInfo.ToLower(value);
                    break;

                case "alphabetic":
                    // TODO:
                    break;

                case "arabic":
                    // TODO:
                    break;

                case "cardtext":
                    // TODO:
                    break;

                case "dollartext":
                    // TODO:
                    break;

                case "hex":
                    // TODO:
                    break;

                case "ordtext":
                    // TODO:
                    break;

                case "ordinal":
                    // TODO:
                    break;

                case "roman":
                    // TODO:
                    break;

                case "charformat":
                    // TODO:
                    break;

                case "mergeformat":
                    // TODO:
                    break;
            }

            return value;
        }

        private static string ProcessNumericSwitch(string switchValue, string value)
        {
            double dblValue = 0;
            bool validNumber = double.TryParse(value, out dblValue);

            // Remove talking marks
            switchValue = switchValue.Replace("\"", "");

            if (validNumber)
            {
                try
                {
                    value = String.Format("{0:" + switchValue + "}", dblValue);
                }
                catch (FormatException)
                { }
            }

            return value;
        }

        private static string ProcessDateTimeSwitch(string switchValue, string value)
        {
            DateTimeOffset dtmValue = new DateTimeOffset();
            bool validDateTime = DateTimeOffset.TryParse(value, out dtmValue);

            // Remove talking marks
            switchValue = switchValue.Replace("\"", "");

            if (validDateTime)
            {
                try
                {
                    value = String.Format("{0:" + switchValue + "}", dtmValue);
                }
                catch (FormatException)
                { }
            }

            return value;
        }

        private static string UppercaseFirst(string value)
        {
            if (string.IsNullOrEmpty(value))
            {
                return string.Empty;
            }

            char[] a = value.ToCharArray();
            a[0] = char.ToUpper(a[0]);

            return new string(a);
        }

        private bool IsUppercaseFirst(string value)
        {
            bool isUpperCase = false;

            if (!string.IsNullOrEmpty(value))
            {
                char[] a = value.ToCharArray();

                if (a[0] == char.ToUpper(a[0]))
                {
                    isUpperCase = true;
                }
            }

            return isUpperCase;
        }

        private string NumberToAlpha(string switchName, string value)
        {
            StringBuilder sb = new StringBuilder();
            string[] alphabet = new string[] { "z", "a", "b", "c", "d", "e", "f", "g", "h", "i", 
                "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y"};

            double dblValue = 0;
            bool validNumber = double.TryParse(value, out dblValue);

            if (validNumber)
            {
                dblValue = Math.Round(dblValue, 0);

                if (dblValue > 0)
                {
                    double lettersRequired = dblValue / 26;

                    int letterIndex = Convert.ToInt32(Math.Floor(lettersRequired));
                    letterIndex = letterIndex * 26;

                    string letter = alphabet[Convert.ToInt32(dblValue) - letterIndex];

                    for (int i = 0; i < Math.Ceiling(lettersRequired); i++)
                    {
                        sb.Append(letter);
                    }
                }
            }

            string retVal = sb.ToString();

            if (this.IsUppercaseFirst(switchName))
            {
                retVal = retVal.ToUpper();
            }

            return retVal;
        }
    }
}
